﻿package com.sdnware.j2se.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class TimeServerHandle implements Runnable {
	
	private Selector selector;
	
	private ServerSocketChannel servChannel;
	
	private volatile boolean stop;
	
	public TimeServerHandle(int port){
		try{
			selector = Selector.open();
			servChannel = ServerSocketChannel.open();
			servChannel.configureBlocking(false);
			servChannel.socket().bind(new InetSocketAddress(port),1024);
			servChannel.register(selector, SelectionKey.OP_ACCEPT);
			System.out.println("The time Server is start in port " + port);
		}catch(IOException ex){
			ex.printStackTrace();
		}
	}
 
	public void stop(){
		this.stop  = true;
	}
	
	public void run() {
		while(!stop){
			try {
				selector.select(1000);
				Set<SelectionKey> selectedKeys = selector.selectedKeys();
				Iterator<SelectionKey> iterator = selectedKeys.iterator();
				SelectionKey key = null;
				while(iterator.hasNext()){
					key = iterator.next();
					iterator.remove();
					try{
						handleInput(key);
					}catch(Exception e){
						e.printStackTrace();
						if(key != null){
							key.cancel();
							if(key.channel() != null){
								key.channel().close();
							}
						}
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if(selector != null){
			try {
				selector.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private void handleInput(SelectionKey key) throws IOException{
		
		if(key.isValid()){
			if(key.isAcceptable()){
				ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
				SocketChannel accept = ssc.accept();
				if(accept != null){
					accept.configureBlocking(false);
					accept.register(selector, SelectionKey.OP_READ);
				}
			}else if(key.isReadable()){
				SocketChannel sc = (SocketChannel)key.channel();
				ByteBuffer readBuffer =ByteBuffer.allocate(1024);
				int readBuffers = sc.read(readBuffer);
				if(readBuffers > 0){
					readBuffer.flip();
					byte[] bytes = new byte[readBuffer.remaining()];
					readBuffer.get(bytes);
					String body = new String(bytes,"UTF-8");
					System.out.println("The time server receive order " + body);
					String currentTime = "QUERY　TIME ORDER".equalsIgnoreCase(body) ? 
							new java.util.Date(System.currentTimeMillis()).toString() : "BAD";
					doWrite(sc,currentTime);
				}else if(readBuffers < 0 ){
					System.out.println("====================1");
					key.channel();
					sc.close();
				}else{
					System.out.println("====================2");
					;
				}
			}
		}
		
	}

	private void doWrite(SocketChannel sc, String response) throws IOException{
		if(response != null && response.trim().length() > 0){
			byte[] bytes = response.getBytes();
			ByteBuffer writerBuffer = ByteBuffer.allocate(bytes.length);
			writerBuffer.put(bytes);
			writerBuffer.flip();
			sc.write(writerBuffer);
		}
	}
}
